﻿/**
 * Created by Richard Radlherr.
 * Date: 23.06.2006 20:10
 */

using System;
using TagTool.Core;
using TagTool.Devices;
using System.Windows.Forms;
using TagTool.Devices.Tablet;
using TagTool.GraphicTypes;

namespace TagTool.Nodes.Devices
{
	public class TabletNode2 : BaseNode
	{
		private ITabletDevice device;
        private ITabletContext context;
        private static TabletManager manager;
		private InputSlot deviceNumber;

		// tablet coordinates
		private OutputSlot location;
		
		// orientation 
		private OutputSlot altitude;
		private OutputSlot azimuth;
		private OutputSlot twist;
		
		private OutputSlot nPressure;
		private OutputSlot tPressure;
		
		// button states
		private OutputSlot btn1;
		private OutputSlot btn2;
		private OutputSlot btn3;
		private OutputSlot btn4;
		
		public TabletNode2() : base()
		{
            location = new OutputSlot(this, "Location", typeof(PointD));
			altitude = new OutputSlot(this, "Altitude", typeof(double));
			azimuth = new OutputSlot(this, "Azimuth", typeof(double));
			twist = new OutputSlot(this, "Twist", typeof(double));
			nPressure = new OutputSlot(this, "NPressure", typeof(double));
			tPressure = new OutputSlot(this, "TPressure", typeof(double));
			btn1 = new OutputSlot(this, "Button 1", typeof(bool));
			btn2 = new OutputSlot(this, "Button 2", typeof(bool));
			btn3 = new OutputSlot(this, "Button 3", typeof(bool));
			btn4 = new OutputSlot(this, "Button 4", typeof(bool));
			
			deviceNumber = new InputSlot(this, "Device Number", 0.0);
			deviceNumber.ParseCallback = ParseHelper.ParseDouble;
			try
			{
				
				if (manager == null)
				{
	            	manager = new TabletManager();
				}
			
            	device = (ITabletDevice)manager.GetDevice(0);
				uint numOfDevices = manager.GetIInfoNumberOfDevices();
				InitDevice();
			}
			catch 
			{
				location.Value = new PointD();
				altitude.Value = 0.0;
				azimuth.Value = 0.0;
				twist.Value = 0.0;
				nPressure.Value = 0.0;
				tPressure.Value = 0.0;
				btn1.Value = false;
				btn2.Value = false;
				btn3.Value = false;
				btn4.Value = false;
				
				Name = "Tablet (not present)";
			}
		}
		
		private void InitDevice()
		{
			if (device != null)
            { 	
	            context = device.DefaultContext;
				context.CursorDeviceEvent += new CursorDeviceEventHandler(OnTabletMove);
	            device.Connect();
	            
	            location.Value = context.Location;
	            altitude.Value = (double)context.Orientation.Altitude;
				azimuth.Value = (double)context.Orientation.Azimuth;
				twist.Value = (double)context.Orientation.Twist;
				nPressure.Value = (double)context.NormalPressure;
				tPressure.Value = (double)context.TangentPressure;
				btn1.Value = ((context.Buttons & 1) > 0);
				btn2.Value = ((context.Buttons & 2) > 0);
				btn3.Value = ((context.Buttons & 4) > 0);
				btn4.Value = ((context.Buttons & 8) > 0);
				
				Name = "Tablet (present)";
            }
            else
            {
            	location.Value = new PointD();
				altitude.Value = 0.0;
				azimuth.Value = 0.0;
				twist.Value = 0.0;
				nPressure.Value = 0.0;
				tPressure.Value = 0.0;
				btn1.Value = false;
				btn2.Value = false;
				btn3.Value = false;
				btn4.Value = false;
				
				Name = "Tablet (not present)";
            }
		}
			
		
		private void OnTabletMove(Object sender, CursorDeviceEventArgs e)
		{
			location.Value = e.Location;
        	
			if (altitude.Value == null || (double)context.Orientation.Altitude != (double)altitude.Value)
			{
				altitude.Value = (double)context.Orientation.Altitude;
			}
			if (azimuth.Value == null || (double)context.Orientation.Azimuth != (double)altitude.Value)
			{
				azimuth.Value = (double)context.Orientation.Azimuth;
			}
			if (twist.Value == null || (double)context.Orientation.Twist != (double)altitude.Value)
			{
				twist.Value = (double)context.Orientation.Twist;
			}
			
			if (nPressure.Value == null || (double)context.NormalPressure != (double)nPressure.Value)
			{
				nPressure.Value = (double)context.NormalPressure;
			}
			if (tPressure.Value == null || (double)context.TangentPressure != (double)tPressure.Value)
			{
				tPressure.Value = (double)context.TangentPressure;
			}
			if (btn1.Value == null || ((context.Buttons & 1) > 0) != (bool)btn1.Value)
			{
				btn1.Value = ((context.Buttons & 1) > 0);
			}
			if (btn2.Value == null || ((context.Buttons & 2) > 0) != (bool)btn2.Value)
			{
				btn2.Value = ((context.Buttons & 2) > 0);
			}
			if (btn3.Value == null || ((context.Buttons & 4) > 0) != (bool)btn3.Value)
			{
				btn3.Value = ((context.Buttons & 4) > 0);
			}
			if (btn4.Value == null || ((context.Buttons & 8) > 0) != (bool)btn4.Value)
			{
				btn4.Value = ((context.Buttons & 8) > 0);
			}
			
			CastTrigger();
		}
		
		public override void Update(Object sender)
		{ // do nothing to update mouse Coordiantes
			int d = (int)((double)deviceNumber.Value);
			device = (ITabletDevice)manager.GetDevice(d);
			if (context != null)
			{
				context.CursorDeviceEvent -= new CursorDeviceEventHandler(OnTabletMove);
			}
			InitDevice();
		}
		
		[NodeAttribute(SlotType.Input, Show = true)]
		public InputSlot DeviceNumber
		{
			get { return deviceNumber; }
		}
		
		[NodeAttribute(SlotType.Output, Show = true)]
		public OutputSlot Location
		{
			get { return location; }
		}

		[NodeAttribute(SlotType.Output, Show = true)]
		public OutputSlot Altitude
		{
			get { return altitude; }
		}
		[NodeAttribute(SlotType.Output, Show = true)]
		public OutputSlot Azimuth
		{
			get { return azimuth; }
		}
		[NodeAttribute(SlotType.Output, Show = true)]
		public OutputSlot Twist
		{
			get { return twist; }
		}
		
		[NodeAttribute(SlotType.Output, Show = true)]
		public OutputSlot NPressure
		{
			get { return nPressure; }
		}
		
		[NodeAttribute(SlotType.Output, Show = true)]
		public OutputSlot TPressure
		{
			get { return tPressure; }
		}
		
		[NodeAttribute(SlotType.Output, Show = true)]
		public OutputSlot Btn1
		{
			get { return btn1; }
		}
		
		[NodeAttribute(SlotType.Output, Show = true)]
		public OutputSlot Btn2
		{
			get { return btn2; }
		}
		
		[NodeAttribute(SlotType.Output, Show = true)]
		public OutputSlot Btn3
		{
			get { return btn3; }
		}
		
		[NodeAttribute(SlotType.Output, Show = true)]
		public OutputSlot Btn4
		{
			get { return btn4; }
		}
	}
}
